Implement try_with_capacity and improve with_capacity - #574
Conversation
|
I think the issue underlying the codebase is much bigger than "we had an unoptimized implementation" if you think about it, why is that faster than what we had?? well, it directly gives information to the compiler of some invariants and changes code paths knowing that before, I don't think this is an issue of "we didn't optimize this function", it is "we have a shitload of methods and implementations on a 2.5k LOC file and surprisingly many of them aren't even doing what they are supposed to do in terms of the abstraction" this may be a bit extreme but I'm proposing a
and we can't even trust the current implementations in it to be neither optimal nor fully safe (remember that memory leak that appeared from nowhere in #450 or the stacked borrow violation in #449) I haven't been opening PRs recently because I have like 5 branches discarded and 20 half-implementations that came across restructuring errors (e.g. manual iterator field magic, more than a 2k LOC replacement PR it would look more like: delete most if modularization has shown something it's that simple modules were easily extracted, core stuff was all intertwined
Request For Comments @bolshoytoster @TDecking @fereidani |
|
I have a problem with not optimizing in alpha stage, I experienced that it is hard to optimize a project when it is nearly finished and already have made wrong choices (explained my opinion in https://fereidani.com/optimization-first-rule-dont-but-aim-for-it). |
|
I agree with @fereidani that's the stance I'm also defending though I'm not in favor of optimizing what we have. why doesn't but instead of making things one I have the impression we are chasing our tail by repeatedly optimizing stuff instead of committing a really good implementation why are we fixing technical debt that's deep into the repo?? honestly the "no performance contributions in alpha" was mostly an ad-hoc rule to focus on architecture first (length, modularization) and avoid trying to fixate ourselves on making small functions a bit faster. the endless structs and assert functions were also pretty annoying, not because they are bad by themselves, but because having them inline is noisy and a module would have been preferred instead, I am in favor of doing so
why not make it once and properly instead of having to review and refactor code that's four years old whilst having to remake core parts of the architecture?? why don't we center our architecture first around performance and not let anything in that's half-baked?? and we are suddenly realizing we are leaving massive gains everywhere?? what I'm most worried about is that when I have to implement something or review something, there's no "default obvious right way of doing so that is fast", but surprisingly 10 different ways with 4 different helper methods that all do pretty much the same except that three do not make assumptions that can be made and are slower about the hot and cold variants, I've never gone deep into that stuff so it looks a bit weird for me, but I guess it makes sense. it's annoying to me but I can understand it, it will make sense once I get more used into that every time you try to understand a new function, like my suggestion is to make a rewrite with the optimizations (which often just means a good architecture and the micro-stuff) instead of having to audit the ~30 possible methods that are not optimized and that do right-but-slightly-unrelated stuff like the current implementation this PR is trying to change |
|
by the way, that post is great. I haven't read it fully but it's really good |
Great!
Many of these optimizations are new even to the rust standard library and are results of many years of experience of rust community and developers, we can't judge them, they did the best they could in their time, we need to do our best now.
Repo itself is valuable in two sense, first it is heavily tested code with more than 1 billion downloads running currently on billions of devices, second we should respect its history and previous contributors, they put great amount of time and effort achieving what it does.
I think we are nearly finished with major perf changes that need restructuring. from now on most perf related PRs will not introduce more lines than what they remove.
If we have same functions doing same thing, we must refactor, even at cost of slight performance(sub percent). Also these links can help you decide when these hard decisions are available(in case you haven't read them): As this library is generic mostly, you can't count assembly instructions directly(count test and bench binary instructions instead), there are some evidence that help you decide really fast if a PR worth merging(from top of my mind, things that I would consider). If it improves performance
Bad points:
It shows a good quality about you, when you are unsure, don't merge it. take your time, analyse it and return back to it.
I'm not sure about this that this is going to improve anything. They are usually independent optimizations with different algorithms.
I would not go that path, we will have to audit much harder, and we don't have luxury of this heavily tested code with that. I think we would have much harder time rewriting it from scratch.
Thank you, Really glad that you liked it. I've updated it today once again, it was missing some cold and inlining guides, and had some minor issues. |
Closes #416.
Also makes
with_capacity~12% faster in the heap case.